﻿#ifndef ELEC_AS_CPP_U1E2
#define ELEC_AS_CPP_U1E2

#include <string>
#include <iostream>
#include <vector>
#include <iterator>

/* Implementation of the Result structure */
struct Result
{
  std::string studentId;
  size_t ex1, ex2, ex3, grade;
};

/* DESCRIPTION:
 * ------------
 * Reads the results data from the parameter input stream, creating new Result elements and
 * appending them to the vector using the parameter the back_insert_iterator.
 *
 * The stream is read until reading fails.
 *
 * The data in the input stream is always in the following format (¶ = new line):
 *
 * <studentId> <ex1> <ex2> <ex3> <grade>¶
 * <studentId> <ex1> <ex2> <ex3> <grade>¶
 *
 * e.g
 *
 * 13337C 6 6 6 5¶
 * 71551T 1 1 1 0¶
 *
 * PARAMETERS:
 * ------------
 * is: the input stream containing the result data.
 * insertIt: back_insert_iterator giving insert access to a results vector
 *
 * RETURNS:
 * ------------
 * The parameter input stream (is).
 *
 */
std::istream& readResults(std::istream& is, std::back_insert_iterator<std::vector<Result>> insertIt);

/* DESCRIPTION:
 * ------------
 * Prints one individual result to the parameter output stream in the following format (¶ = new line):
 *
 * <studentId> <ex1> <ex2> <ex3> <grade>¶
 *
 * e.g
 *
 * 13337C 6 6 6 5¶
 *
 * PARAMETERS:
 * ------------
 * os: the output stream where to print the result
 * result: an iterator pointing to the result
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */
void printResult(std::ostream& os, std::vector<Result>::const_iterator result);

/* DESCRIPTION:
 * ------------
 * Prints all the results between [begin,end) to the output stream. The print format is the same as in
 * printResult.
 *
 * PARAMETERS:
 * ------------
 * os: the output stream where to print the result
 * begin: iterator pointing to the first result to be printed
 * end: iterator pointing to the end of the area to be printed (not printed)
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */
void printResults(std::ostream& os, std::vector<Result>::const_iterator begin, std::vector<Result>::const_iterator end);

/* DESCRIPTION:
 * ------------
 * Compares the grades of all results between the parameter vector's [begin,end)
 * and removes all results with grades equal to the parameter grade from the 
 * results vector.
 * 
 * PARAMETERS:
 * ------------
 * results: a reference to the vector containing the results
 * grade: specifies the grades, which are removed
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */
void removeResultIf(std::vector<Result>& results, size_t grade);

/* DESCRIPTION:
 * ------------
 * Compares the student ids of all results between [begin,end) and returns the first match found. 
 * 
 * PARAMETERS:
 * ------------
 * begin: iterator pointing to the first result included in the search
 * end: iterator pointing to the end of the search area (not included in the search)
 * student id: specifies the student id to find
 *
 * RETURNS:
 * ------------
 * If the student id is found returns an iterator pointing to the first result with the matching
 * student id.
 *
 * If the student id is not found returns the parameter end iterator.
 *
 */
std::vector<Result>::const_iterator findResult(std::vector<Result>::const_iterator begin, std::vector<Result>::const_iterator end, std::string const& studentId);

/* DESCRIPTION:
 * ------------
 * Copies all results from the range [begin,end) using the parameter inserter.
 *
 * PARAMETERS:
 * ------------
 * begin: iterator pointing to the first result to be copied
 * end: iterator pointing to the end of the copy area (not included in the copy)
 * insertIt: back_insert_iterator giving insert access to the target vector
 *
 * RETURNS:
 * ------------
 * Nothing.
 *
 */
void copyResults(std::vector<Result>::const_iterator begin, std::vector<Result>::const_iterator end, std::back_insert_iterator<std::vector<Result>> insertIt);

#endif
